package com.eatme.web.sys.workflow.activiti.controller;

import com.eatme.web.common.QueryCondition;
import com.eatme.web.common.vo.AppResponse;
import org.activiti.api.model.shared.model.VariableInstance;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.ProcessDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.security.Principal;
import java.util.*;

@Controller
@RequestMapping("process/instance/")
public class ProcessInstanceController {
    private static final Logger LOG = LoggerFactory.getLogger(ProcessInstanceController.class);

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ProcessRuntime processRuntime;

    @Autowired
    private RuntimeService runtimeService;

    //查询流程实例
    @PostMapping("list")
    @ResponseBody
    public AppResponse list(@RequestBody QueryCondition<Map<String,Object>> queryCondition)  {
        Integer pageSize = queryCondition.getPage().getPageSize();
        Integer pageIndex = queryCondition.getPage().getPageIndex();
        // 需要登陆
        Page<ProcessInstance> processInstancePage = processRuntime.processInstances(Pageable.of(pageIndex,pageSize));
        List<ProcessInstance> list = processInstancePage.getContent();
        list.sort((y, x) -> x.getStartDate().toString().compareTo(y.getStartDate().toString()));// 排序
        // 因为 ProcessInstance 流程实例没有历史高亮的deploymentID和资源Name,所以需要再次查询
        List<Map<String, Object>> arrayList = new ArrayList<>();
        for (ProcessInstance pi : list) {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("id", pi.getId());
            hashMap.put("name", pi.getName());
            hashMap.put("status", pi.getStatus());
            hashMap.put("processDefinitionId", pi.getProcessDefinitionId());
            hashMap.put("processDefinitionKey", pi.getProcessDefinitionKey());
            hashMap.put("startDate", pi.getStartDate());
            hashMap.put("processDefinitionVersion", pi.getProcessDefinitionVersion());
            //因为processRuntime.processDefinition("流程部署ID")查询的结果没有部署流程与部署ID，所以用repositoryService查询
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(pi.getProcessDefinitionId())
                    .singleResult();
            hashMap.put("resourceName", pd.getResourceName());
            hashMap.put("deploymentId", pd.getDeploymentId());
            arrayList.add(hashMap);
        }
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("total",processInstancePage.getTotalItems());
        if (!list.isEmpty()){
            resultMap.put("list",arrayList);
        }
        return AppResponse.ok().data(resultMap);
    }

    //启动流程实例
    @PostMapping(value = "/start")
    @ResponseBody
    public AppResponse startProcess(@RequestBody Map<String,Object> map,Principal principal) {
        //1、获取页面表单填报的内容，请假时间，请假事由，String fromData
        //2、fromData 写入业务表，返回业务表主键ID==businessKey
        //3、把业务数据与Activiti7流程数据关联
        String processDefinitionKey = (String) map.get("processDefinitionKey");
        String instanceName = (String) map.get("instanceName");
        String businessKey = (String) map.get("businessKey");
        String processDefinitionId = (String) map.get("processDefinitionId");
        Map<String,Object> variablesMap = (Map<String, Object>) map.get("instanceVariable");
        Authentication.setAuthenticatedUserId(principal.getName());
        ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
                .start()
                .withProcessDefinitionKey(processDefinitionKey)
                                //.withProcessDefinitionId(processDefinitionId)
//                .withProcessDefinitionId(processDefinitionId)
                .withName(instanceName)
//                .withVariables(variablesMap)
//                .withBusinessKey(businessKey)
                .build());
        return AppResponse.ok();

    }

    //挂起流程实例
    @PostMapping(value = "/suspend")
    @ResponseBody
    public AppResponse suspendInstance(@RequestBody Map<String,Object> map) {
        String processInstanceId = (String) map.get("processInstanceId");
        runtimeService.suspendProcessInstanceById(processInstanceId);
        // TODO The following code has bug need fix;
//        ProcessInstance processInstance = processRuntime.suspend(ProcessPayloadBuilder
//                .suspend()
//                .withProcessInstanceId(processInstanceId)
//                .build()
//        );
        return AppResponse.ok();
    }

    //激活/重启流程实例
    @PostMapping(value = "/resume")
    @ResponseBody
    public AppResponse resumeInstance(@RequestBody Map<String,Object> map) {
        String processInstanceId = (String) map.get("processInstanceId");
        runtimeService.activateProcessInstanceById(processInstanceId);
        // TODO The following code has bug need fix;
//        ProcessInstance processInstance = processRuntime.resume(ProcessPayloadBuilder
//                .resume()
//                .withProcessInstanceId(processInstanceId)
//                .build()
//        );

        return AppResponse.ok();
    }
    //删除流程实例
    @PostMapping(value = "/delete")
    @ResponseBody
    public AppResponse deleteInstance(@RequestBody Map<String,Object> map) {
        String processInstanceId = (String) map.get("processInstanceId");
        String deleteReason = (String) map.get("deleteReason");
        runtimeService.deleteProcessInstance(processInstanceId,deleteReason);
        // TODO The following code has bug need fix;
//        ProcessInstance processInstance = processRuntime.delete(ProcessPayloadBuilder
//                .delete()
//                .withProcessInstanceId(processInstanceId)
//                .build()
//        );
            return AppResponse.ok();

    }

    //查询流程参数
    @PostMapping(value = "/variables")
    @ResponseBody
    public AppResponse variables(Map<String,Object> map) {
        String processInstanceId = (String) map.get("processInstanceId");
            List<VariableInstance> variableInstances = processRuntime.variables(ProcessPayloadBuilder
                    .variables()
                    .withProcessInstanceId(processInstanceId)
                    .build());

            return AppResponse.ok().data(variableInstances);
    }


}
